﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SqlSugarAndEntity.Base;
using SqlSugarAndEntity.Entity;
using WebApi.Middlewares.Attributes;
using Core.JwtService;
using Common.HttpHelper;

namespace WebApi.Middlewares;

// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class LogMiddleware
{
    private readonly RequestDelegate _next;
    private IBaseMethod baseMethod;

    public LogMiddleware(RequestDelegate next, IBaseMethod baseMethod)
    {
        _next = next;
        this.baseMethod = baseMethod;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        //先判断这个请求是否需要记录日志
        var attr = HttpContextHelper.GetMetadata<IgnoreLogAttribute>(httpContext);
        //不需要记录日志 直接走
        if (attr != null)
        {
            await _next(httpContext);
        }
        else
        {
            sys_loginfo loginfo = new sys_loginfo();
            Stopwatch stopwatch = new Stopwatch();
            //计时
            stopwatch.Start();
            //拦截请求,获得请求参数
            if (httpContext.Request.Headers.TryGetValue("Authorzation", out var apiKeyHeaderValues))
            {
                var userinfo = JwtExtensions.GetData<sys_userinfo>(apiKeyHeaderValues.ToString());
                loginfo.UserId = userinfo.ID;
            }
            loginfo.UserIP = httpContext.Connection.RemoteIpAddress?.ToString();
            loginfo.RequestMethod = httpContext.Request.Method.Trim().ToUpper();
            loginfo.RequestPath = httpContext.Request.Path;
            if (loginfo.RequestMethod == "GET" || loginfo.RequestMethod == "DELETE")
            {
                loginfo.RequestParameter = httpContext.Request.QueryString.Value;
            }
            else
            {
                var pamara = await HttpContextHelper.GetRequestBody(httpContext.Request.Body);
                //擦除用户密码
                if (pamara.ContainsKey("UserPassWord"))
                {
                    pamara.Remove("UserPassWord");
                }
                loginfo.RequestParameter = pamara.ToString();
            }
            //执行正常逻辑
            var originalBodyStream = httpContext.Response.Body;
            using (var responseBody = new MemoryStream())
            {
                httpContext.Response.Body = responseBody;
                await _next(httpContext);
                stopwatch.Stop();
                loginfo.CreateTime = DateTime.Now;
                loginfo.Duration = (int)stopwatch.ElapsedMilliseconds;
                JObject obj = await HttpContextHelper.GetResponse(httpContext.Response);
                await responseBody.CopyToAsync(originalBodyStream);
                string res = JsonConvert.SerializeObject(obj);
                loginfo.ResponseResult = res;
                loginfo.ResponseCode = obj.Value<int>("code");
            }
            httpContext.Response.OnCompleted(() =>
            {
                baseMethod.Db().Insertable(loginfo).ExecuteCommandAsync();
                return Task.CompletedTask;
            });


        }
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class LogMiddlewareExtensions
{
    public static IApplicationBuilder UseLogMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<LogMiddleware>();
    }
}

